home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 1372.ZIP / PIBCAT.ARC / PIBCAT.PAS < prev    next >
Pascal/Delphi Source File  |  1988-11-07  |  51KB  |  1,175 lines

  1. (*$V-,R-,S-,B-,I-,F+*)
  2. PROGRAM PibCat;
  3.  
  4. (*----------------------------------------------------------------------*)
  5. (*                                                                      *)
  6. (*    Program: PIBCAT --- Catalog files on a disk.                      *)
  7. (*                                                                      *)
  8. (*    Author:  Philip R. Burns.                                         *)
  9. (*                                                                      *)
  10. (*    Version: 1.5.   November 7, 1988.                                 *)
  11. (*                                                                      *)
  12. (*    Usage:                                                            *)
  13. (*           PIBCAT v /f=filespec /i=indent /m=margin /l /m=margin /n   *)
  14. (*                    /o=filename /p=pagesize /t=timezone /x /2         *)
  15. (*                                                                      *)
  16. (*            v               volume (drive letter) to catalog          *)
  17. (*                            (default is current drive)                *)
  18. (*                            If given as ?, this text is displayed.    *)
  19. (*            /e=filespec     DOS file spec to match when listing       *)
  20. (*                            entries in .ARC/.DWC/.LBR/.MD/.ZOO files  *)
  21. (*                            (default is *.* -- list all entries).     *)
  22. (*            /f=filespec     DOS file spec to match when listing files *)
  23. (*                            (default is *.* -- list all files)        *)
  24. (*            /i=indent       # columns to space for library entries    *)
  25. (*                            (default is 0)                            *)
  26. (*            /l              display long file names in .ZOO and .MD   *)
  27. (*                            files (default is to display short file   *)
  28. (*                            names only)                               *)
  29. (*            /m=margin       left margin to leave (default is 0)       *)
  30. (*            /n              expand libraries after main catalog       *)
  31. (*                            listing rather than immediately after     *)
  32. (*                            library file name (default is to expand   *)
  33. (*                            immediately following file name).         *)
  34. (*            /o=filename     write catalog listing to file "filename"  *)
  35. (*                            (default is "CATALOG.LIS")                *)
  36. (*            /p=pagesize     paginate listing using "pagesize" lines   *)
  37. (*                            (default is no pagination)                *)
  38. (*            /t=timezone     number of hours local time lags/leads     *)
  39. (*                            Greenwich Mean Time [GMT] (default is 7)  *)
  40. (*            /x              don't list library file contents          *)
  41. (*                            (default is to list contents)             *)
  42. (*            /2              Opens files without SHARE for DOS v2.x    *)
  43. (*                            compatibility (default is to open files   *)
  44. (*                            with share for DOS v3.1 and above)        *)
  45. (*                                                                      *)
  46. (*    Aborting:  Hit ^C to abort catalog listing.                       *)
  47. (*                                                                      *)
  48. (*    Output:                                                           *)
  49. (*                                                                      *)
  50. (*       For each selected file, the file name, size in bytes, and time *)
  51. (*       and date of creation are displayed.  The same information is   *)
  52. (*       given for members of .ARC, .DWC, .LBR, .MD, and .ZOO files.    *)
  53. (*                                                                      *)
  54. (*    Restrictions:                                                     *)
  55. (*                                                                      *)
  56. (*       None.  I contribute this program and all source code to the    *)
  57. (*       public domain.                                                 *)
  58. (*                                                                      *)
  59. (*       I do ask as a matter of courtesy that you give me credit if    *)
  60. (*       you use this code in your own applications.                    *)
  61. (*                                                                      *)
  62. (*    Acknowledgments:                                                  *)
  63. (*                                                                      *)
  64. (*       The archive search code is based upon TPARCV.PAS written by    *)
  65. (*       Michael Quinlan and ARCV.ASM written by Vern Buerg.            *)
  66. (*                                                                      *)
  67. (*       The library search code is based upon LU.PAS written by        *)
  68. (*       Steve Freeman.                                                 *)
  69. (*                                                                      *)
  70. (*       Stephen Falatko suggested and coded the enhancement to list    *)
  71. (*       the contents of .ARC, .LBR files immediately following their   *)
  72. (*       appearance in the main catalog listing.  I've altered the      *)
  73. (*       display to make it easier to pick those entries which are .ARC *)
  74. (*       and .LBR contents.                                             *)
  75. (*                                                                      *)
  76. (*       Dave Seidman provided a mechanism for getting the volume label *)
  77. (*       under MS DOS 2.x.                                              *)
  78. (*                                                                      *)
  79. (*       The format for the .ZOO files was taken from the "C" source    *)
  80. (*       code to ZOO written by Rahul Dhesi.                            *)
  81. (*                                                                      *)
  82. (*       The format for the .MD files was extracted from the code       *)
  83. (*       provided by Mike Davenport.                                    *)
  84. (*                                                                      *)
  85. (*       The format for the .DWC files was extracted from the code      *)
  86. (*       provided by Dean W. Cooper for his DWC program.                *)
  87. (*                                                                      *)
  88. (*    Note:                                                             *)
  89. (*                                                                      *)
  90. (*      The routines for processing the various library files are all   *)
  91. (*      extremely similar.  I could have merged them into one big       *)
  92. (*      routine to avoid the duplicate code.  However, I felt it was    *)
  93. (*      a better idea to leave them separate, even with the extensive   *)
  94. (*      code duplication, so that you could extract the ones you wanted *)
  95. (*      without having to wade through stuff unrelated to the library   *)
  96. (*      format of interest to you.                                      *)
  97. (*                                                                      *)
  98. (*----------------------------------------------------------------------*)
  99.  
  100.                                    (* Global declarations *)
  101. (*$I PIBCAT.GLO    *)
  102.                                    (* General service subroutines *)
  103. (*$I PIBCATS1.PAS  *)
  104. (*$I PIBCATS2.PAS  *)
  105.  
  106. (*----------------------------------------------------------------------*)
  107. (*        Display_Help  --- Display help screen for PibCat              *)
  108. (*----------------------------------------------------------------------*)
  109.  
  110. PROCEDURE Display_Help;
  111.  
  112. VAR
  113.    Ch: CHAR;
  114.  
  115. BEGIN (* Display_Help *)
  116.  
  117.    WRITELN;
  118.    WRITELN('Program: PIBCAT --- Catalog files on a disk.');
  119.    WRITELN('Author:  Philip R. Burns.');
  120.    WRITELN('Version: 1.5   November 7, 1988.');
  121.    WRITELN('Usage:   PIBCAT v /f=filespec /i=indent /m=margin /o=filename /p=pagesize /x /n');
  122.    WRITELN('                v               volume (drive letter) to catalog');
  123.    WRITELN('                                (default is current drive)');
  124.    WRITELN('                                If given as ?, this text is displayed.');
  125.    WRITELN('                /e=filespec     DOS file spec to match when listing');
  126.    WRITELN('                                entries in .ARC/.DWC/.LBR/.MD/.ZOO files');
  127.    WRITELN('                                (default is *.* -- list all entries).');
  128.    WRITELN('                /f=filespec     DOS file spec to match when listing files');
  129.    WRITELN('                                (default is *.* -- list all files)');
  130.    WRITELN('                /i=indent       # columns to space for library entries');
  131.    WRITELN('                                (default is 0)');
  132.    WRITELN('                /l              display long file names in .ZOO and .MD');
  133.    WRITELN('                                files (default is to display short file');
  134.    WRITELN('                                names only)');
  135.    WRITELN('                /m=margin       left margin to leave (default is 0)');
  136.    WRITELN('                /n              list contents of libraries at end of each');
  137.    WRITELN('                                subdirectory (default is list contents');
  138.    WRITELN('                                following library file name)');
  139.    WRITELN('                /o=filename     write catalog listing to file "filename"');
  140.    WRITELN('                                (default is "CATALOG.LIS")');
  141.    WRITELN(' ');
  142.  
  143.    WRITE  ('Hit a key to continue: ');
  144.    READ( Ch );
  145.  
  146.    WHILE( KeyPressed ) DO
  147.       READ( Ch );
  148.  
  149.    WRITELN;
  150.    WRITELN;
  151.    WRITELN('                /p=pagesize     paginate listing using "pagesize" lines');
  152.    WRITELN('                                (default is no pagination)');
  153.    WRITELN('                /t=timezone     number of hours local time lags/leads Greenwich');
  154.    WRITELN('                                Mean Time [GMT] (default is 7)');
  155.    WRITELN('                /x              don''t list library file contents');
  156.    WRITELN('                                (default is to list contents)');
  157.    WRITELN('                /2              Opens files without SHARE for DOS v2.x');
  158.    WRITELN('                                compatibility (default is to open files');
  159.    WRITELN('                                with share for DOS v3.1 and above)');
  160.    WRITELN;
  161.    WRITELN('Aborting:  Hit ^C to abort catalog listing.');
  162.    WRITELN;
  163.  
  164. END   (* Display_Help *);
  165.  
  166. (*----------------------------------------------------------------------*)
  167. (*             Initialize --- Initialize PibCat program                 *)
  168. (*----------------------------------------------------------------------*)
  169.  
  170. FUNCTION Initialize : BOOLEAN;
  171.  
  172. VAR
  173.    S    : AnyStr;
  174.    S2   : AnyStr;
  175.    I    : INTEGER;
  176.    J    : INTEGER;
  177.    IErr : INTEGER;
  178.  
  179. (* STRUCTURED *) CONST
  180.    Legit_Drives : SET OF CHAR = ['A'..'Z','?'];
  181.  
  182. BEGIN (* Initialize *)
  183.                                    (* --- Set defaults --- *)
  184.  
  185.                                    (* Drive to catalog is current drive *)
  186.    GetDir( 0 , S );
  187.    Cat_Drive         := UpCase( S[1] );
  188.  
  189.                                    (* Default output file is CATALOG.LIS *)
  190.  
  191.    Output_File_Name  := 'CATALOG.LIS';
  192.  
  193.                                    (* Don't produce paginated listing file *)
  194.    Do_Printer_Format := FALSE;
  195.    Page_Size         := 0;
  196.                                    (* No extra spaces at left margin *)
  197.    Left_Margin       := 0;
  198.                                    (* No extra indent for libraries *)
  199.    Library_Indent    := 0;
  200.                                    (* List contents of library files *)
  201.    Expand_Libs       := TRUE;
  202.                                    (* Expand libraries after main listing *)
  203.    Expand_Libs_In    := TRUE;
  204.                                    (* No ^C hit yet terminating cataloguing *)
  205.    User_Break        := FALSE;
  206.                                    (* Catalog all files by default *)
  207.    Find_Spec         := '*.*';
  208.                                    (* Catalog all library entries by default *)
  209.    Entry_Spec        := '*.*';
  210.                                    (* We start on first page *)
  211.    Page_Number       := 1;
  212.                                    (* Lots of lines left on this page *)
  213.    Lines_Left        := 32767;
  214.                                    (* No files yet *)
  215.    File_Count        := 0;
  216.    Total_Files       := 0;
  217.    Total_Space       := 0;
  218.    Total_Entries     := 0;
  219.    Total_ESpace      := 0;
  220.    Total_Dirs        := 0;
  221.                                    (* No titles yet *)
  222.    Volume_Title      := '';
  223.    Subdir_Title      := '';
  224.    File_Title        := '';
  225.                                    (* Not help mode only *)
  226.    Help_Only         := FALSE;
  227.                                    (* Only short file names by default *)
  228.    Show_Long_File_Names := FALSE;
  229.                                    (* Assume we are using SHARE    *)
  230.    Use_Share         := TRUE;                                     
  231.                                    (* # of seconds local time leads/lags *)
  232.                                    (* Greenwich Mean Time (GMT)          *)
  233.  
  234.    GMT_Difference       := 8 * 3600;
  235.  
  236.                                    (* Assume we do daylight savings adjustment *)
  237.    Use_Daylight_Savings := TRUE;
  238.    
  239.                                    (* Grab command line parameters *)
  240.    FOR I := 1 TO ParamCount DO
  241.       BEGIN
  242.  
  243.          S := UpperCase( ParamStr( I ) );
  244.  
  245.          IF ( S[1] = '/' ) THEN
  246.             BEGIN
  247.  
  248.                IF ( S[3] = '=' ) THEN
  249.                   S2 := COPY( S, 4, LENGTH( S ) - 3 )
  250.                ELSE
  251.                   S2 := '';
  252.  
  253.                CASE UpCase( S[2] ) OF
  254.  
  255.                                    (* Match entry within libraries *)
  256.                   'E':  BEGIN
  257.                            IF ( S2 <> '' ) THEN
  258.                               Entry_Spec := S2;
  259.                         END;
  260.                                    (* Match this file spec *)
  261.                   'F':  BEGIN
  262.                            IF ( S2 <> '' ) THEN
  263.                               Find_Spec := S2;
  264.                         END;
  265.                                    (* # of space to indent when listing *)
  266.                                    (* contents of libraries             *)
  267.                   'I':  BEGIN
  268.                            VAL( S2, J, IErr );
  269.                            IF ( IErr = 0 ) THEN
  270.                               Library_Indent := J;
  271.                         END;
  272.  
  273.                                    (* If long file names should be listed *)
  274.                                    
  275.                   'L':  Show_Long_File_Names := TRUE;
  276.  
  277.                                    (* # of space in left margin of output *)
  278.                   'M':  BEGIN
  279.                            VAL( S2, J, IErr );
  280.                            IF ( IErr = 0 ) THEN
  281.                               Left_Margin := J;
  282.                         END;
  283.  
  284.                                    (* Expand libraries after all files *)
  285.                                    (* listed in a subdirectory         *)
  286.                   'N':  BEGIN
  287.                            Expand_Libs_In   := FALSE;
  288.                            Expand_Libs      := TRUE;
  289.                         END;
  290.                                    (* Output file name *)
  291.                                    
  292.                   'O':  Output_File_Name := S2;
  293.  
  294.                                    (* Page size for printing *)
  295.  
  296.                   'P':  BEGIN
  297.  
  298.                            VAL( S2, J, IErr );
  299.  
  300.                            IF ( IErr = 0 ) THEN
  301.                               BEGIN
  302.                                  Page_Size  := J;
  303.                                  Lines_Left := J;
  304.                               END;
  305.  
  306.                            Do_Printer_Format := ( Page_Size > 0 );
  307.  
  308.                         END;
  309.                                    (* Number of hours or minutes local time *)
  310.                                    (* leads/lags Greenwich Mean Time        *)
  311.                   'T':  BEGIN
  312.  
  313.                            IF ( LENGTH( S2 ) > 0 ) THEN 
  314.                               BEGIN
  315.  
  316.                                  J := LENGTH( S2 );
  317.                                  
  318.                                  IF ( S2[ J ] = 'A' ) THEN
  319.                                     BEGIN
  320.                                        DELETE( S2 , J , 1 );
  321.                                        Use_Daylight_Savings := FALSE;
  322.                                     END;
  323.                                     
  324.                                  VAL( S2, J, IErr );
  325.  
  326.                                  IF ( IErr = 0 ) THEN
  327.                                     GMT_Difference := J;
  328.  
  329.                                  IF ( ABS ( GMT_Difference ) <= 12 ) THEN
  330.                                     GMT_Difference := GMT_Difference * 3600
  331.                                  ELSE
  332.                                     GMT_Difference := GMT_Difference * 60;   
  333.  
  334.                                  IF ( ABS( GMT_Difference  ) > ( 12 * 3600 ) ) THEN
  335.                                     GMT_Difference := 8 * 3600;    
  336.  
  337.                               END;
  338.  
  339.                         END;
  340.                                    (* If library contents should be expanded *)
  341.  
  342.                   'X':  Expand_Libs := FALSE;
  343.  
  344.                                    (* If SHARE to be used when opening files *)
  345.  
  346.                   '2':  Use_Share   := FALSE;
  347.                   
  348.                   ELSE;
  349.  
  350.                END (* CASE *);
  351.  
  352.             END
  353.          ELSE
  354.             IF ( S[1] IN Legit_Drives ) THEN
  355.                Cat_Drive := S[1];
  356.       END;
  357.                                    (* If the drive was a "?" then we have  *)
  358.                                    (* a help request.  Display help info   *)
  359.                                    (* and quit.                            *)
  360.    IF ( Cat_Drive = '?' ) THEN
  361.       BEGIN
  362.          Display_Help;
  363.          Initialize := FALSE;
  364.          Help_Only  := TRUE;
  365.          EXIT;
  366.       END;
  367.                                    (* Fix up entry spec for comparisons    *)
  368.                                    (* later on.  If '*.*', then don't      *)
  369.                                    (* bother with entry spec checks later. *)
  370.  
  371.    Check_Entry_Spec( Entry_Spec, Entry_Name, Entry_Ext, Use_Entry_Spec );
  372.  
  373.                                    (* Get string of blanks for left margin *)
  374.  
  375.    Left_Margin_String := DUPL( ' ' , Left_Margin );
  376.  
  377.                                    (* Get DOS version and set open *)
  378.                                    (* file modes accordingly.      *)
  379.  
  380.    IF ( ( Dos_Version >= 31 ) AND Use_Share ) THEN
  381.       BEGIN
  382.          Read_Open_Mode  := 32;
  383.          Write_Open_Mode := 34;
  384.       END
  385.    ELSE
  386.       BEGIN
  387.          Read_Open_Mode  := 0;
  388.          Write_Open_Mode := 2;
  389.       END;
  390.                                    (* Open output file *)
  391.    FileMode := Write_Open_Mode;
  392.  
  393.    ASSIGN( Output_File , Output_File_Name );
  394.    SetTextBuf( Output_File , Output_File_Buffer );
  395.    REWRITE( Output_File );
  396.  
  397.    FileMode := 2;
  398.                                    (* Continue if we got it *)
  399.    IF ( IOResult <> 0 ) THEN
  400.       BEGIN
  401.          WRITELN;
  402.          WRITELN( 'Can''t open output file ', Output_File_Name );
  403.          WRITELN;
  404.          Initialize := FALSE;
  405.          EXIT;
  406.       END;
  407.                                    (* Prevent heap allocation death *)
  408.  
  409.    HeapError := @Heap_Error_Handler;
  410.  
  411.                                    (* See how many file segments we can get *)
  412.  
  413.    Stack_Alloc := PRED( ( MemAvail - 8192 ) DIV SIZEOF( File_Stack_Type ) );
  414.  
  415.                                    (* If we can't allocate even one segment *)
  416.                                    (* then report error and quit.           *)
  417.    IF ( Stack_Alloc < 0 ) THEN
  418.       BEGIN
  419.          WRITELN;
  420.          WRITELN( 'Not enough memory to process file directories ' );
  421.          WRITELN;
  422.          Initialize := FALSE;
  423.          EXIT;
  424.       END
  425.    ELSE
  426.                                    (* Otherwise, allocate the segments *)
  427.       FOR I := 0 TO Stack_Alloc DO
  428.          NEW( File_Stack[ I ] );
  429.  
  430.                                    (* Get bracketing Unix dates for   *)
  431.                                    (* daylight savings time calcs.    *)
  432.    Get_Daylight_Savings_Times;
  433.  
  434.                                    (* Indicate initialization went OK *)
  435.    Initialize := TRUE;
  436.  
  437. END   (* Initialize *);
  438.  
  439. (*----------------------------------------------------------------------*)
  440. (*     Display_Volume_Label   ---  Display volume label of disk         *)
  441. (*----------------------------------------------------------------------*)
  442.  
  443. PROCEDURE Display_Volume_Label;
  444.  
  445. VAR
  446.    Volume_Label : AnyStr;
  447.    Vol_Time     : LONGINT;
  448.    STime        : STRING[10];
  449.    SDate        : STRING[10];
  450.  
  451. BEGIN (* Display_Volume_Label *)
  452.  
  453.                                    (* Blank out volume title line *)
  454.  
  455.    Volume_Title := DUPL( ' ' , 80 );
  456.  
  457.                                    (* Get volume label from DOS *)
  458.  
  459.    Dir_Get_Volume_Label( Cat_Drive, Volume_Label, Vol_Time );
  460.  
  461.    WRITELN( Output_File );
  462.                                    (* If no volume label, don't output it. *)
  463.  
  464.    IF ( Volume_Label = '' ) THEN
  465.       BEGIN
  466.  
  467.          Volume_Title := Left_Margin_String              +
  468.                          ' Contents of volume on drive ' +
  469.                          Cat_Drive                       +
  470.                          ' as of '                       +
  471.                          DateString                      +
  472.                          '  '                            +
  473.                          TimeOfDayString;
  474.  
  475.          IF Do_Printer_Format THEN
  476.             BEGIN
  477.                WRITELN( Output_File , FF_Char );
  478.                WRITE  ( Output_File , Volume_Title );
  479.                WRITELN( Output_File , '     Page ', Page_Number );
  480.             END
  481.          ELSE
  482.             WRITELN( Output_File , Volume_Title );
  483.  
  484.          DEC( Lines_Left );
  485.  
  486.       END
  487.    ELSE
  488.                                    (* If volume label, output it along with *)
  489.                                    (* its creation time and date.           *)
  490.       BEGIN
  491.  
  492.          Volume_Title := Left_Margin_String        +
  493.                          ' Contents of volume '    +
  494.                          Volume_Label              +
  495.                          ' as of '                 +
  496.                          DateString                +
  497.                          '  '                      +
  498.                          TimeOfDayString;
  499.  
  500.          IF Do_Printer_Format THEN
  501.             BEGIN
  502.                WRITELN( Output_File , FF_Char );
  503.                WRITE  ( Output_File , Volume_Title );
  504.                WRITELN( Output_File , '     Page ', Page_Number );
  505.             END
  506.          ELSE
  507.             WRITELN( Output_File , Volume_Title );
  508.  
  509.          Volume_Label := Volume_Label + DUPL( ' ' , 12 - LENGTH( Volume_Label ) );
  510.  
  511.          Dir_Convert_Date_And_Time( Vol_Time , SDate , STime );
  512.  
  513.          WRITELN( Output_File );
  514.          WRITE  ( Output_File , Left_Margin_String,
  515.                   ' Volume: ',Volume_Label );
  516.  
  517.          IF ( SDate <> '         ' ) THEN
  518.             WRITE  ( Output_File , ' Created: ', SDate, '  ', STime );
  519.  
  520.          DEC( Lines_Left , 3 );
  521.  
  522.       END;
  523.  
  524.    WRITELN( Output_File );
  525.                                    (* Count lines left on page *)
  526.    DEC( Lines_Left , 2 );
  527.  
  528. END   (* Display_Volume_Label *);
  529.  
  530. (*----------------------------------------------------------------------*)
  531. (*     Display_Page_Titles  ---  Display page titles at top of page     *)
  532. (*----------------------------------------------------------------------*)
  533.  
  534. PROCEDURE Display_Page_Titles;
  535.  
  536. (*----------------------------------------------------------------------*)
  537. (*                                                                      *)
  538. (*    Procedure: Display_Page_Titles;                                   *)
  539. (*                                                                      *)
  540. (*    Purpose:   Displays page headers for paginated output file        *)
  541. (*                                                                      *)
  542. (*    Calling sequence:                                                 *)
  543. (*                                                                      *)
  544. (*       Display_Page_Titles;                                           *)
  545. (*                                                                      *)
  546. (*----------------------------------------------------------------------*)
  547.  
  548. BEGIN (* Display_Page_Titles *)
  549.  
  550.                                    (* Skip to top of new page using FF *)
  551.    WRITELN( Output_File , FF_Char );
  552.  
  553.                                    (* Reset lines left to page size    *)
  554.    Lines_Left  := Page_Size;
  555.                                    (* Increment page count             *)
  556.  
  557.    INC( Page_Number );
  558.  
  559.                                    (* Display extant titles            *)
  560.                                    (*   -- Volume title                *)
  561.  
  562.    WRITELN( Output_File );
  563.    WRITELN( Output_File , Volume_Title , '     Page ', Page_Number );
  564.    WRITELN( Output_File );
  565.                                    (*   -- Subdirectory title          *)
  566.  
  567.    WRITELN( Output_File , Subdir_Title );
  568.    WRITELN( Output_File );
  569.  
  570.    DEC( Lines_Left , 5 );
  571.  
  572.    IF ( File_Title <> '' ) THEN
  573.       BEGIN
  574.                                    (*   -- File title          *)
  575.  
  576.          WRITELN( Output_File , File_Title );
  577.          WRITELN( Output_File );
  578.  
  579.          DEC( Lines_Left , 2 );
  580.  
  581.       END;
  582.  
  583. END   (* Display_Page_Titles *);
  584.  
  585. (*----------------------------------------------------------------------*)
  586. (*          Include code to process library files.                      *)
  587. (*----------------------------------------------------------------------*)
  588.  
  589.                                    (* .ARC display routines    *)
  590. (*$I PIBCATA.PAS *)
  591.                                    (* .DWC display routines    *)
  592. (*$I PIBCATD.PAS *)
  593.                                    (* .LBR display routines    *)
  594. (*$I PIBCATL.PAS *)
  595.                                    (* .MD display routines     *)
  596. (*$I PIBCATM.PAS *)
  597.                                    (* .ZOO display routines    *)
  598. (*$I PIBCATZ.PAS *)
  599.  
  600. (*----------------------------------------------------------------------*)
  601. (*          Move_File_Info --- Save file information for sorting        *)
  602. (*----------------------------------------------------------------------*)
  603.  
  604. PROCEDURE Move_File_Info(     Full : SearchRec;
  605.                           VAR Short: Short_Dir_Record );
  606.  
  607. (*----------------------------------------------------------------------*)
  608. (*                                                                      *)
  609. (*    Procedure: Move_File_Info                                         *)
  610. (*                                                                      *)
  611. (*    Purpose:   Saves information about file in compact form           *)
  612. (*                                                                      *)
  613. (*    Calling sequence:                                                 *)
  614. (*                                                                      *)
  615. (*       Move_File_Info(     Full : SearchRec;                          *)
  616. (*                       VAR Short: Short_Dir_Record );                 *)
  617. (*                                                                      *)
  618. (*          Full  --- Directory info as retrieved from DOS              *)
  619. (*          Short --- Directory info with garbage thrown out            *)
  620. (*                                                                      *)
  621. (*    Remarks:                                                          *)
  622. (*                                                                      *)
  623. (*       This routine copies the useful stuff about a file to a         *)
  624. (*       shorter record which is more easily sorted.                    *)
  625. (*                                                                      *)
  626. (*----------------------------------------------------------------------*)
  627.  
  628. BEGIN (* Move_File_Info *)
  629.  
  630.    Short.File_Time    := Full.Time;
  631.    Short.File_Size    := Full.Size;
  632.    Short.File_Attr    := Full.Attr;
  633.    Short.File_Name    := Full.Name + DUPL( ' ' , 12 - LENGTH( Full.Name ) );
  634.  
  635. END   (* Move_File_Info *);
  636.  
  637. (*----------------------------------------------------------------------*)
  638. (*        Display_File_Info --- Display information about a file        *)
  639. (*----------------------------------------------------------------------*)
  640.  
  641. PROCEDURE Display_File_Info( Dir_Entry : Short_Dir_Record );
  642.  
  643. (*----------------------------------------------------------------------*)
  644. (*                                                                      *)
  645. (*    Procedure: Display_File_Info                                      *)
  646. (*                                                                      *)
  647. (*    Purpose:   Displays information for current file                  *)
  648. (*                                                                      *)
  649. (*    Calling sequence:                                                 *)
  650. (*                                                                      *)
  651. (*       Display_File_Info( Dir_Entry : Short_Dir_Record );             *)
  652. (*                                                                      *)
  653. (*          Dir_Entry --- Directory record describing file              *)
  654. (*                                                                      *)
  655. (*    Remarks:                                                          *)
  656. (*                                                                      *)
  657. (*       The counters for total number of files and total file space    *)
  658. (*       used are incremented here.                                     *)
  659. (*                                                                      *)
  660. (*----------------------------------------------------------------------*)
  661.  
  662. VAR
  663.    RLength : LONGINT;
  664.    STime   : STRING[10];
  665.    SDate   : STRING[10];
  666.    I       : INTEGER;
  667.  
  668. BEGIN (* Display_File_Info *)
  669.  
  670.    WITH Dir_Entry DO
  671.       BEGIN
  672.                                    (* Ensure space left this page *)
  673.  
  674.          IF ( Lines_Left < 1 ) THEN
  675.             Display_Page_Titles;
  676.                                    (* Get length *)
  677.  
  678.          RLength := File_Size;
  679.  
  680.                                    (* Get date and time of creation *)
  681.  
  682.          Dir_Convert_Date_And_Time( File_Time , SDate , STime );
  683.  
  684.                                    (* Write out file name *)
  685.  
  686.          WRITE( Output_File , Left_Margin_String , '      ' , File_Name );
  687.  
  688.          FOR I := LENGTH( File_Name ) TO 14 DO
  689.             WRITE( Output_File , ' ');
  690.  
  691.                                    (* Write length, date, and time *)
  692.  
  693.          WRITE  ( Output_File , RLength:8, '  ' );
  694.          WRITE  ( Output_File , SDate, '  ' );
  695.          WRITE  ( Output_File , STime );
  696.          WRITELN( Output_File );
  697.  
  698.                                    (* Update count of lines left   *)
  699.          IF Do_Printer_Format THEN
  700.             DEC( Lines_Left );
  701.  
  702.       END;
  703.                                    (* Increment total file count   *)
  704.  
  705.    INC( Total_Files );
  706.  
  707.                                    (* Increment total space used   *)
  708.  
  709.    Total_Space := Total_Space + RLength;
  710.  
  711. END   (* Display_File_Info *);
  712.  
  713. (*----------------------------------------------------------------------*)
  714. (*          Sort_Files --- Sort files in ascending order by name        *)
  715. (*----------------------------------------------------------------------*)
  716.  
  717. PROCEDURE Sort_Files( First : INTEGER;
  718.                       Last  : INTEGER );
  719.  
  720. (*----------------------------------------------------------------------*)
  721. (*                                                                      *)
  722. (*    Procedure: Sort_Files                                             *)
  723. (*                                                                      *)
  724. (*    Purpose:   Sorts file names in current directory                  *)
  725. (*                                                                      *)
  726. (*    Calling sequence:                                                 *)
  727. (*                                                                      *)
  728. (*       Sort_Files( First : INTEGER; Last : INTEGER );                 *)
  729. (*                                                                      *)
  730. (*          First --- First entry in 'File_Stack' to sort               *)
  731. (*          Last  --- Last entry in 'File_Stack' to sort                *)
  732. (*                                                                      *)
  733. (*    Remarks:                                                          *)
  734. (*                                                                      *)
  735. (*       A shell sort is used to put the file names for the current     *)
  736. (*       directory in ascending order.  The current directory's files   *)
  737. (*       are bracketed by 'First' and 'Last'.                           *)
  738. (*                                                                      *)
  739. (*----------------------------------------------------------------------*)
  740.  
  741. VAR
  742.    Temp : Short_Dir_Record;
  743.    I    : INTEGER;
  744.    J    : INTEGER;
  745.    D    : INTEGER;
  746.  
  747. BEGIN (* Sort_Files *)
  748.  
  749.    D := SUCC( Last - First );
  750.  
  751.    WHILE( D > 1 ) DO
  752.       BEGIN
  753.  
  754.          IF ( D < 5 ) THEN
  755.             D := 1
  756.          ELSE
  757.             D := TRUNC( 0.45454 * D );
  758.  
  759.          FOR I := ( Last - D ) DOWNTO First DO
  760.             BEGIN
  761.  
  762.                Temp       := File_Stack[ I SHR SegShift ]^[ I AND MaxFiles ];
  763.                J          := I + D;
  764.  
  765.                WHILE( ( Temp.File_Name >
  766.                         File_Stack[ J SHR SegShift ]^[ J AND MaxFiles ].File_Name ) AND
  767.                       ( J <= Last ) ) DO
  768.                   BEGIN
  769.                      File_Stack[ ( J - D ) SHR SegShift ]^[ ( J - D ) AND MaxFiles ] :=
  770.                         File_Stack[ J SHR SegShift ]^[ J AND MaxFiles ];
  771.                      J               := J + D;
  772.                   END;
  773.  
  774.                File_Stack[ ( J - D ) SHR SegShift ]^[ ( J - D ) AND MaxFiles ] := Temp;
  775.  
  776.             END;
  777.  
  778.       END;
  779.  
  780. END   (* Sort_Files *);
  781.  
  782. (*----------------------------------------------------------------------*)
  783. (*          Find_Files --- Recursively search directories for files     *)
  784. (*----------------------------------------------------------------------*)
  785.  
  786. PROCEDURE Find_Files( VAR Subdir    : AnyStr;
  787.                       VAR File_Spec : AnyStr;
  788.                           Attr      : INTEGER;
  789.                           Levels    : INTEGER );
  790.  
  791. (*----------------------------------------------------------------------*)
  792. (*                                                                      *)
  793. (*    Procedure: Find_Files                                             *)
  794. (*                                                                      *)
  795. (*    Purpose:   Recursively traverses directories looking for files    *)
  796. (*                                                                      *)
  797. (*    Calling sequence:                                                 *)
  798. (*                                                                      *)
  799. (*       Find_Files( VAR Subdir    : AnyStr;                            *)
  800. (*                   VAR File_Spec : AnyStr;                            *)
  801. (*                       Attr      : INTEGER;                           *)
  802. (*                       Levels    : INTEGER );                         *)
  803. (*                                                                      *)
  804. (*          Subdir    --- subdirectory name of this level               *)
  805. (*          File_Spec --- DOS file spec to match                        *)
  806. (*          Attr      --- attribute type to match                       *)
  807. (*          Levels    --- current subdirectory level depth              *)
  808. (*                                                                      *)
  809. (*    Remarks:                                                          *)
  810. (*                                                                      *)
  811. (*       This is the actual heart of PibCat.  This routine invokes      *)
  812. (*       itself recursively to traverse all subdirectories looking for  *)
  813. (*       files which match the given file specification.                *)
  814. (*                                                                      *)
  815. (*----------------------------------------------------------------------*)
  816.  
  817. VAR
  818.    Dir_Entry  : SearchRec;
  819.    Path       : AnyStr;
  820.    Error      : INTEGER;
  821.    I          : INTEGER;
  822.    Dir        : STRING[14];
  823.    Cur_Count  : INTEGER;
  824.    Skip_Attr  : INTEGER;
  825.    Files_Here : INTEGER;
  826.    ISeg       : INTEGER;
  827.    IOff       : INTEGER;
  828.  
  829. LABEL  Quit;
  830.  
  831. BEGIN  (* Find_Files *)
  832.                                    (* Save current file count *)
  833.    Cur_Count  := File_Count;
  834.                                    (* No files in this directory yet *)
  835.    Files_Here := 0;
  836.                                    (* Don't list directories as files *)
  837.  
  838.    Skip_Attr := VolumeID + Directory;
  839.  
  840.    IF ( Levels >= 1 ) THEN
  841.       BEGIN
  842.                                    (* Get full file spec to search for *)
  843.  
  844.          Path := Subdir + File_Spec;
  845.  
  846.                                    (* Get first file on this level *)
  847.  
  848.          FindFirst( Path, AnyFile, Dir_Entry );
  849.          Error := DosError;
  850.  
  851.                                    (* Get info on remaining files  *)
  852.                                    (* on this level.               *)
  853.          WHILE ( Error = 0 ) DO
  854.             BEGIN
  855.                                    (* Increment count of files in this dir *)
  856.                                    (* including subdirectories             *)
  857.  
  858.                INC( File_Count );
  859.  
  860.                                    (* Increment non-directory file count *)
  861.  
  862.                IF ( ( Dir_Entry.Attr AND Skip_Attr ) = 0 ) THEN
  863.                    INC( Files_Here );
  864.  
  865.                                    (* Save info on this file *)
  866.  
  867.                Move_File_Info ( Dir_Entry ,
  868.                                 File_Stack[ File_Count SHR SegShift ]^[ File_Count AND MaxFiles ] );
  869.  
  870.                                    (* Get next file entry *)
  871.  
  872.                FindNext( Dir_Entry );
  873.                Error := DosError;
  874.  
  875.                                    (* Check for ^C at keyboard *)
  876.                IF KeyPressed THEN
  877.                   IF QuitFound THEN
  878.                      GOTO Quit;
  879.  
  880.             END;
  881.                                    (* Sort file names              *)
  882.  
  883.          Sort_Files( SUCC( Cur_Count ) , File_Count );
  884.  
  885.                                    (* Increment directory count    *)
  886.          INC ( Total_Dirs );
  887.  
  888.                                    (* Report scanning this subdirectory *)
  889.  
  890.          WRITELN(' Scanning: ', Subdir );
  891.  
  892.                                    (* Display file info header *)
  893.  
  894.          IF ( Files_Here > 0 ) THEN
  895.             BEGIN
  896.  
  897.                Subdir_Title := Left_Margin_String + ' Directory: ' + Subdir;
  898.  
  899.                IF Do_Printer_Format THEN
  900.                   IF ( Lines_Left < 4 ) THEN
  901.                      Display_Page_Titles
  902.                   ELSE
  903.                      BEGIN
  904.                         WRITELN( Output_File );
  905.                         WRITELN( Output_File , Subdir_Title );
  906.                         WRITELN( Output_File );
  907.                      END
  908.                ELSE
  909.                   BEGIN
  910.                      WRITELN( Output_File );
  911.                      WRITELN( Output_File , Subdir_Title );
  912.                      WRITELN( Output_File );
  913.                   END;
  914.                                    (* Count lines left on page *)
  915.  
  916.                IF Do_Printer_Format THEN
  917.                   BEGIN
  918.                      DEC( Lines_Left , 3 );
  919.                      IF ( Lines_Left < 1 ) THEN
  920.                         Display_Page_Titles;
  921.                   END;
  922.  
  923.             END;
  924.                                    (* Display info on all files       *)
  925.                                    (* But don't display directories!  *)
  926.  
  927.          FOR I := SUCC( Cur_Count ) TO File_Count DO
  928.              BEGIN
  929.  
  930.                 ISeg := I SHR SegShift;
  931.                 IOff := I AND MaxFiles;
  932.  
  933.                 IF ( ( File_Stack[ ISeg ]^[ IOff ].File_Attr AND Skip_Attr ) = 0 ) THEN
  934.                    Display_File_Info( File_Stack[ ISeg ]^[ IOff ] );
  935.  
  936.                 IF ( Expand_Libs AND Expand_Libs_In ) THEN
  937.                    BEGIN
  938.                       IF      ( POS( '.ARC', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  939.                          Display_Archive_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  940.                       ELSE IF ( POS( '.PAK', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  941.                          Display_Archive_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  942.                       ELSE IF ( POS( '.DWC', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  943.                          Display_DWC_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  944.                       ELSE IF ( POS( '.LBR', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  945.                          Display_Lbr_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  946.                       ELSE IF ( POS( '.MD ', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  947.                          Display_MD_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  948.                       ELSE IF ( POS( '.ZOO', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  949.                          Display_ZOO_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name );
  950.                    END;
  951.  
  952.                 IF KeyPressed THEN
  953.                    IF QuitFound THEN
  954.                       GOTO Quit;
  955.  
  956.              END;
  957.                                    (* List library file contents if requested *)
  958.  
  959.          IF ( Expand_Libs AND ( NOT Expand_Libs_In ) ) THEN
  960.             BEGIN
  961.                                    (* List contents of any .ARC files *)
  962.  
  963.                FOR I := SUCC( Cur_Count ) TO File_Count DO
  964.                   BEGIN
  965.  
  966.                      ISeg := I SHR SegShift;
  967.                      IOff := I AND MaxFiles;
  968.  
  969.                                    (* If current file is any type of   *)
  970.                                    (* library file, then list contents *)
  971.  
  972.                      IF      ( POS( '.ARC', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  973.                         Display_Archive_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  974.                      ELSE IF ( POS( '.PAK', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  975.                         Display_Archive_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  976.                      ELSE IF ( POS( '.DWC', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  977.                          Display_DWC_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  978.                      ELSE IF ( POS( '.LBR', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  979.                         Display_Lbr_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  980.                      ELSE IF ( POS( '.MD ', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  981.                         Display_MD_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name )
  982.                      ELSE IF ( POS( '.ZOO', File_Stack[ ISeg ]^[ IOff ].File_Name ) > 0 ) THEN
  983.                         Display_ZOO_Contents( Subdir + File_Stack[ ISeg ]^[ IOff ].File_Name );
  984.  
  985.                                    (* If <CTRL>Break hit, quit. *)
  986.  
  987.                      IF KeyPressed THEN
  988.                         IF QuitFound THEN
  989.                            GOTO Quit;
  990.  
  991.                   END;
  992.  
  993.             END;
  994.  
  995.          IF ( Levels >= 2 ) THEN
  996.             BEGIN
  997.                                    (* List all subdirectories to given level *)
  998.                                    (* Note: we read through whole directory  *)
  999.                                    (*       again since we probably excluded *)
  1000.                                    (*       directories on first pass.       *)
  1001.  
  1002.                Path := Subdir + '*.*';
  1003.  
  1004.                                    (* Get first file *)
  1005.  
  1006.                FindFirst( Path, AnyFile, Dir_Entry );
  1007.                Error := DosError;
  1008.  
  1009.                                    (* While there are files left ... *)
  1010.  
  1011.                WHILE ( Error = 0 ) DO
  1012.                   BEGIN
  1013.                                    (* See if it's a subdirectory *)
  1014.  
  1015.                      IF ( ( Dir_Entry.Attr AND Directory ) <> 0 ) THEN
  1016.                         BEGIN
  1017.                                    (* Yes -- get subdirectory name *)
  1018.  
  1019.                            Dir := Dir_Entry.Name;
  1020.  
  1021.                                    (* Ignore '.' and '..' *)
  1022.  
  1023.                            IF ( ( Dir <> '.' ) AND ( Dir <> '..') ) THEN
  1024.                               BEGIN
  1025.  
  1026.                                    (* Construct path name for subdirectory *)
  1027.  
  1028.                                  Path := Subdir + Dir + '\';
  1029.  
  1030.                                    (* List files in subdirectory *)
  1031.  
  1032.                                  Find_Files( Path, File_Spec, Attr, PRED( Levels ) );
  1033.  
  1034.                                  IF User_Break THEN
  1035.                                     GOTO Quit;
  1036.  
  1037.                               END;
  1038.  
  1039.                         END;
  1040.                                    (* Get next file entry *)
  1041.  
  1042.                      FindNext( Dir_Entry );
  1043.                      Error := DosError;
  1044.  
  1045.                   END (* WHILE *);
  1046.  
  1047.             END (* IF Levels >= 2 *);
  1048.  
  1049.       END (* IF Levels >= 1 *);
  1050.                                    (* Restore previous file count *)
  1051. Quit:
  1052.    File_Count := Cur_Count;
  1053.  
  1054. END   (* Find_Files *);
  1055.  
  1056. (*----------------------------------------------------------------------*)
  1057. (*             Perform_Cataloguing --- Do cataloguing of files          *)
  1058. (*----------------------------------------------------------------------*)
  1059.  
  1060. PROCEDURE Perform_Cataloguing;
  1061.  
  1062. VAR
  1063.    Name      : AnyStr;
  1064.    Subdir    : AnyStr;
  1065.    File_Spec : AnyStr;
  1066.    I         : INTEGER;
  1067.    L         : INTEGER;
  1068.    Done      : BOOLEAN;
  1069.  
  1070. BEGIN (* Perform_Cataloguing *)
  1071.                                    (* Display volume label       *)
  1072.    Display_Volume_Label;
  1073.                                    (* Append disk letter to file spec *)
  1074.  
  1075.    IF ( POS( '\' , Find_Spec ) = 0 ) THEN
  1076.       Name := Cat_Drive + ':\' + Find_Spec
  1077.    ELSE
  1078.       Name := Cat_Drive + ':' + Find_Spec;
  1079.  
  1080.                                    (* Make sure some files get looked at! *)
  1081.  
  1082.    IF Name[LENGTH(Name)] = '\' THEN
  1083.       Name := Name + '*.*';
  1084.  
  1085.                                    (* Split out directory from file spec *)
  1086.    Subdir := Name;
  1087.    I      := SUCC( LENGTH( Subdir ) );
  1088.    Done   := FALSE;
  1089.  
  1090.    REPEAT
  1091.       DEC( I );
  1092.       IF ( I > 0 ) THEN
  1093.          Done := ( Subdir[I] = '\' )
  1094.       ELSE
  1095.          Done := TRUE;
  1096.    UNTIL Done;
  1097.  
  1098.    I := LENGTH( Subdir ) - I;
  1099.  
  1100.    File_Spec[0] := CHR( I );
  1101.  
  1102.    MOVE( Subdir[ 1 + LENGTH( Subdir ) - I ] , File_Spec[ 1 ] , I );
  1103.  
  1104.    Subdir[0] := CHR( LENGTH( Subdir ) - I );
  1105.  
  1106.                                    (* Begin listing files at specified *)
  1107.                                    (* subdirectory                     *)
  1108.  
  1109.    Find_Files( Subdir, File_Spec, $FF, 9999 );
  1110.  
  1111. END   (* Perform_Cataloguing *);
  1112.  
  1113. (*----------------------------------------------------------------------*)
  1114. (*                Terminate --- Terminate cataloguing                   *)
  1115. (*----------------------------------------------------------------------*)
  1116.  
  1117. PROCEDURE Terminate;
  1118.  
  1119. VAR
  1120.    I : INTEGER;
  1121.  
  1122. BEGIN (* Terminate *)
  1123.                                    (* Note if catalogue terminated by ^C *)
  1124.    IF ( NOT Help_Only ) THEN
  1125.       IF User_Break THEN
  1126.          BEGIN
  1127.             IF ( Lines_Left < 6 ) THEN
  1128.                Display_Page_Titles;
  1129.             WRITELN( Output_File );
  1130.             WRITELN( Output_File , Left_Margin_String,
  1131.                      '>>>>> ^C typed, catalog listing INCOMPLETE.');
  1132.             WRITELN( Output_File );
  1133.             WRITELN( '^C typed, catalog listing INCOMPLETE.');
  1134.          END
  1135.       ELSE
  1136.          BEGIN                        (* Indicate file totals *)
  1137.             IF ( Lines_Left < 9 ) THEN
  1138.                Display_Page_Titles;
  1139.             WRITELN( Output_File );
  1140.             WRITELN( Output_File , Left_Margin_String, ' Totals:');
  1141.             WRITELN( Output_File , Left_Margin_String,
  1142.                      '    Directories scanned: ',Total_Dirs:10);
  1143.             WRITELN( Output_File , Left_Margin_String,
  1144.                      '    Files selected     : ',Total_Files:10);
  1145.             WRITELN( Output_File , Left_Margin_String,
  1146.                      '    Bytes in files     : ',Total_Space:10);
  1147.             WRITELN( Output_File , Left_Margin_String,
  1148.                      '    Entries selected   : ',Total_Entries:10);
  1149.             WRITELN( Output_File , Left_Margin_String,
  1150.                      '    Bytes in entries   : ',Total_ESpace:10);
  1151.             WRITELN( Output_File , Left_Margin_String,
  1152.                      '    Bytes free         : ',
  1153.                      DiskFree( SUCC( ORD( Cat_Drive ) - ORD('A') ) ):10 );
  1154.          END;
  1155.                                    (* Close output file *)
  1156.       (*$I-*)
  1157.    CLOSE( Output_File );
  1158.       (*$I+*)
  1159.    IF ( IOResult <> 0 ) THEN;
  1160.  
  1161. END   (* Terminate *);
  1162.  
  1163. (*---------------------- Main Program of PIBCAT ------------------------*)
  1164.  
  1165. BEGIN (* PibCat *)
  1166.                                    (* Initialize program.  If initialization *)
  1167.                                    (* goes OK, then perform cataloguing.     *)
  1168.    IF Initialize THEN
  1169.       Perform_Cataloguing;
  1170.                                    (* Close output file and terminate.       *)
  1171.    Terminate;
  1172.  
  1173. END   (* PibCat *).
  1174.  
  1175.